#include "SwitchSliderWidget.h"
#include <QPainter>    // 绘图类，用于绘制控件
#include <QMouseEvent> // 鼠标事件类
#include <QKeyEvent>   // 键盘事件类
#include <QEasingCurve> // 动画曲线类，用于平滑过渡

/**
 * @brief 构造函数：初始化控件状态和样式参数
 * @param parent 父窗口指针
 */
SwitchSliderWidget::SwitchSliderWidget(QWidget *parent)
    : QWidget(parent),  // 初始化父类
      m_checked(true),  // 默认状态为打开
      m_sliderPosition(0),  // 滑块初始位置
      m_backgroundColor(QColor("#165DFF")),  // 默认背景色
      m_pressed(false),  // 初始未按下
      m_animation(nullptr),  // 动画对象初始为空
      m_width(42),  // 默认宽度
      m_height(21),  // 默认高度
      m_sliderRadius(8),  // 滑块半径
      m_checkedColor("#165DFF"),  // 打开状态颜色（蓝色）
      m_uncheckedColor("#e0e0e0") // 关闭状态颜色（浅灰）
{
    setFixedSize(m_width, m_height);  // 设置控件固定尺寸
    setCursor(Qt::PointingHandCursor);  // 鼠标悬停时显示手型光标
    setFocusPolicy(Qt::StrongFocus);  // 允许获取焦点，支持键盘操作
    m_sliderPosition = maxSliderPosition();  // 初始化滑块到右侧（打开状态）
}

/**
 * @brief 获取当前开关状态
 * @return 开关状态（true为打开）
 */
bool SwitchSliderWidget::isChecked() const
{
    return m_checked;
}

/**
 * @brief 设置开关状态并处理动画
 * @param checked 目标状态
 * @param animate 是否启用动画
 */
void SwitchSliderWidget::setChecked(bool checked, bool animate)
{
    // 如果状态没有变化，直接返回
    if (m_checked == checked)
        return;

    m_checked = checked;  // 更新状态

    // 停止并清理当前动画（如果存在）
    if (m_animation && m_animation->state() == QPropertyAnimation::Running) {
        m_animation->stop();
        delete m_animation;
        m_animation = nullptr;
    }

    if (animate) {
        // 创建滑块位置动画
        m_animation = new QPropertyAnimation(this, "sliderPosition", this);
        m_animation->setDuration(300);                  // 动画持续300ms
        m_animation->setStartValue(m_sliderPosition);   // 起始位置
        // 目标位置：打开时在右侧，关闭时在左侧
        m_animation->setEndValue(m_checked ? maxSliderPosition() : 0);
        m_animation->setEasingCurve(QEasingCurve::InOutCubic);      // 平滑曲线
        m_animation->start(QAbstractAnimation::DeleteWhenStopped);  // 结束后自动删除

        // 连接动画结束信号，防止悬空指针
        connect(m_animation, &QPropertyAnimation::finished, this, [this]() {
            m_animation = nullptr;
        });

        // 创建背景颜色过渡动画
        QPropertyAnimation *colorAnim = new QPropertyAnimation(this, "backgroundColor", this);
        colorAnim->setDuration(300);  // 颜色动画持续300ms
        colorAnim->setStartValue(m_backgroundColor);  // 起始颜色
        colorAnim->setEndValue(m_checked ? m_checkedColor : m_uncheckedColor);  // 目标颜色
        colorAnim->setEasingCurve(QEasingCurve::InOutCubic);  // 平滑曲线
        colorAnim->start(QAbstractAnimation::DeleteWhenStopped);  // 结束后自动删除
    } else {
        // 无动画：直接更新位置和颜色
        setSliderPosition(m_checked ? maxSliderPosition() : 0);
        setBackgroundColor(m_checked ? m_checkedColor : m_uncheckedColor);
    }

    emit toggled(m_checked);  // 发送状态变化信号
}

/**
 * @brief 获取滑块当前位置
 * @return 滑块X坐标
 */
int SwitchSliderWidget::sliderPosition() const
{
    return m_sliderPosition;
}

/**
 * @brief 设置滑块位置并触发重绘
 * @param position 目标位置
 */
void SwitchSliderWidget::setSliderPosition(int position)
{
    m_sliderPosition = position;
    update();  // 触发重绘
}

/**
 * @brief 获取当前背景颜色
 * @return 背景颜色对象
 */
QColor SwitchSliderWidget::backgroundColor() const
{
    return m_backgroundColor;
}

/**
 * @brief 设置背景颜色并触发重绘
 * @param color 目标颜色
 */
void SwitchSliderWidget::setBackgroundColor(const QColor &color)
{
    m_backgroundColor = color;
    update();  // 触发重绘
}

/**
 * @brief 调整控件尺寸
 * @param width 新宽度
 * @param height 新高度
 */
void SwitchSliderWidget::setSwitchSize(int width, int height)
{
    m_width = width;
    m_height = height;
    setFixedSize(m_width, m_height);  // 更新固定尺寸
    // 重新计算滑块位置以适应新尺寸
    setSliderPosition(m_checked ? maxSliderPosition() : 0);
}

/**
 * @brief 计算滑块最大可移动位置（右侧终点）
 * @return 最大位置值
 */
int SwitchSliderWidget::maxSliderPosition() const
{
    // 宽度减去滑块直径（左右各留一个半径）
    return m_width - 2 * m_sliderRadius;
}

/**
 * @brief 重绘控件外观
 * @param event 事件对象（未使用）
 */
void SwitchSliderWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);  // 标记参数未使用

    QPainter painter(this);  // 创建绘图对象
    painter.setRenderHint(QPainter::Antialiasing, true);  // 启用抗锯齿，使边缘平滑

    // 绘制背景圆角矩形
    QRect backgroundRect = rect();          // 获取控件矩形区域
    painter.setBrush(m_backgroundColor);    // 设置背景画刷
    painter.setPen(Qt::NoPen);              // 取消边框线

    // 绘制圆角矩形（圆角半径为高度的一半，使其成为胶囊形状）
    painter.drawRoundedRect(backgroundRect, m_height / 2, m_height / 2);

    // 绘制焦点/按下状态的边框
    if (hasFocus() || m_pressed) {
        painter.setBrush(Qt::NoBrush);          // 取消填充
        painter.setPen(Qt::NoPen);  // 设置边框画笔
//        QRect focusRect = backgroundRect.adjusted(1, 1, -1, -1);  // 缩小1px的矩形
//        // 绘制焦点边框（圆角稍小）
//        painter.drawRoundedRect(focusRect, (m_height - 2) / 2, (m_height - 2) / 2);
        painter.drawRoundedRect(backgroundRect, (m_height - 2) / 2, (m_height - 2) / 2);
    }

    // 绘制白色滑块
    painter.setBrush(Qt::white);                    // 白色填充
    painter.setPen(QPen(QColor("#e0e0e0"), 1));     // 浅灰色边框
    // 绘制圆形滑块（中心坐标：X=滑块位置+半径，Y=高度的一半）
    painter.drawEllipse(
        QPoint(m_sliderPosition + m_sliderRadius, m_height / 2),
        m_sliderRadius,
        m_sliderRadius
    );
}

/**
 * @brief 处理鼠标按下事件
 * @param event 鼠标事件对象
 */
void SwitchSliderWidget::mousePressEvent(QMouseEvent *event)
{
    // 仅处理左键点击且在控件范围内的事件
    if (event->button() == Qt::LeftButton && rect().contains(event->pos())) {
        m_pressed = true;   // 标记为按下状态
        update();           // 重绘以显示按下效果
        event->accept();    // 接受事件，不再传递
    } else {
        // 其他情况交给父类处理
        QWidget::mousePressEvent(event);
    }
}

/**
 * @brief 处理鼠标释放事件
 * @param event 鼠标事件对象
 */
void SwitchSliderWidget::mouseReleaseEvent(QMouseEvent *event)
{
    // 处理左键释放且之前处于按下状态的事件
    if (event->button() == Qt::LeftButton && m_pressed) {
        // 只有当鼠标释放时仍在控件内才切换状态
        if (rect().contains(event->pos())) {
            setChecked(!m_checked);     // 切换状态
            emit clicked();             // 发送点击信号
        }
        m_pressed = false;              // 重置按下状态
        update();                       // 重绘以更新外观
        event->accept();                // 接受事件
    } else {
        m_pressed = false;              // 重置按下状态
        update();                       // 重绘
        // 其他情况交给父类处理
        QWidget::mouseReleaseEvent(event);
    }
}

/**
 * @brief 处理键盘事件，支持空格键控制
 * @param event 键盘事件对象
 */
void SwitchSliderWidget::keyPressEvent(QKeyEvent *event)
{
    // 处理空格键
    if (event->key() == Qt::Key_Space) {
        setChecked(!m_checked);             // 切换状态
        emit clicked();                     // 发送点击信号
        event->accept();                    // 接受事件
    } else {
        // 其他按键交给父类处理
        QWidget::keyPressEvent(event);
    }
}

/**
 * @brief 提供控件的建议尺寸
 * @return 建议尺寸
 */
QSize SwitchSliderWidget::sizeHint() const
{
    return QSize(m_width, m_height);  // 返回当前设置的尺寸
}
